import pandas as pd
from scipy.io import arff
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer
from sklearn.svm import SVC
from sklearn.metrics import classification_report, confusion_matrix, roc_curve, auc
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.decomposition import PCA
import numpy as np

# 读取 .arff 文件
file_path = r'D:\EDAG下载\NASADefectDataset-master\OriginalData\MDP\CM1.arff'
# data 是数据部分，meta是包含数据集的元信息（比如属性名、数据类型等）
data, meta = arff.loadarff(file_path)

# 将 ARFF 数据转换为 Pandas DataFrame，以便进一步进行数据处理
df = pd.DataFrame(data)

# 处理数据类型， applymap 表示用于对DataFrame的每个元素应用一个函数，由于 ARFF 文件中可能存在字节类型数据，这里将字节数据解码为字符串。
df = df.applymap(lambda x: x.decode() if isinstance(x, bytes) else x)

# 处理缺失值
imputer = SimpleImputer(strategy='mean')  # 或选择 'median' 或 'most_frequent'
df_imputed = pd.DataFrame(imputer.fit_transform(df.select_dtypes(include=['number'])), columns=df.select_dtypes(include=['number']).columns)

# 处理标签列
# 将 Defective 列中的标签从 'Y' 和 'N' 转换为 1 和 0，以便进行机器学习处理。N代表存在问题，Y代表不存在
df_imputed['Defective'] = df['Defective'].apply(lambda x: 1 if x == 'Y' else 0)

# 特征和标签
# X 包含所有特征（即除去标签列的所有列）
# y 是标签列（即 Defective）
X = df_imputed.drop('Defective', axis=1)
y = df_imputed['Defective']

# 数据标准化
# StandardScaler 用于标准化特征，使其具有均值为 0 和标准差为 1
# fit_transform 对数据进行标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 划分数据集
# train_test_split 用于将数据集划分为训练集和测试集
# test_size=0.3 表示 30% 的数据用于测试集，其余用于训练集
# random_state=42 确保每次运行代码时划分结果一致。
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.3, random_state=42)

# 训练 SVM 模型
# 创建一个线性核的支持向量机（SVM）模型。
model = SVC(kernel='linear', probability=True)
model.fit(X_train, y_train)

# 预测
# predict 方法生成测试数据的预测标签。
# predict_proba 生成测试数据的预测概率，其中 [:, 1] 表示提取属于类别 1 （Y，不存在问题）的概率
y_pred = model.predict(X_test)
y_pred_prob = model.predict_proba(X_test)[:, 1]

# 评估模型
# classification_report 计算分类模型的精确度、召回率、F1 分数等指标，并以字典形式返回
report = classification_report(y_test, y_pred, output_dict=True)
# confusion_matrix 计算混淆矩阵，用于显示真实标签和预测标签的对比
conf_matrix = confusion_matrix(y_test, y_pred)
print(report)
print(conf_matrix)

# 定义颜色
color_0 = 'skyblue'
color_1 = 'lightgreen'

# 创建类别0的评估指标直方图
metrics_0 = {
    'Accuracy': report['accuracy'],
    'Precision_0': report['0']['precision'],
    'Recall_0': report['0']['recall'],
    'F1_Score_0': report['0']['f1-score']
}

plt.figure(figsize=(6, 6))
plt.bar(metrics_0.keys(), metrics_0.values(), color=color_0)
plt.title('Classification Metrics for Class 0 (No Defect)')
plt.ylabel('Score')
plt.tight_layout()
plt.savefig('picture/SVM/pclassification_metrics_0.png')  # 保存文件到当前目录
plt.show()

# 创建类别1的评估指标直方图
metrics_1 = {
    'Accuracy': report['accuracy'],
    'Precision_1': report['1']['precision'],
    'Recall_1': report['1']['recall'],
    'F1_Score_1': report['1']['f1-score']
}

plt.figure(figsize=(6, 6))
plt.bar(metrics_1.keys(), metrics_1.values(), color=color_1)
plt.title('Classification Metrics for Class 1 (Defect)')
plt.ylabel('Score')
plt.tight_layout()
plt.savefig('picture/SVM/classification_metrics_1.png')  # 保存文件到当前目录
plt.show()

# 计算ROC曲线和AUC
fpr, tpr, _ = roc_curve(y_test, y_pred_prob)
roc_auc = auc(fpr, tpr)

# 创建ROC曲线图
plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC curve (area = {roc_auc:.2f})')
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic (ROC)')
plt.legend(loc='lower right')
plt.tight_layout()
plt.savefig('picture/SVM/roc_curve_and_auc.png')  # 保存文件到当前目录
plt.show()

# 创建一个热图显示混淆矩阵
plt.figure(figsize=(8, 6))
sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues',
            xticklabels=['No Defect', 'Defect'],
            yticklabels=['No Defect', 'Defect'])
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.title('Confusion Matrix')
plt.savefig('picture/SVM/Confusion_Matrix.png')
plt.show()
#
# # 绘制 ROC 曲线
# fpr, tpr, _ = roc_curve(y_test, y_pred_prob)
# roc_auc = auc(fpr, tpr)
#
# plt.figure(figsize=(8, 6))
# plt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve (area = %0.2f)' % roc_auc)
# plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
# plt.xlim([0.0, 1.0])
# plt.ylim([0.0, 1.05])
# plt.xlabel('False Positive Rate')
# plt.ylabel('True Positive Rate')
# plt.title('Receiver Operating Characteristic (ROC)')
# plt.legend(loc='lower right')
# plt.show()
# # 从分类报告中提取评估指标
# report_dict = report
# labels = [0 , 1 ]  # 标签名称
#
# # 提取每个标签的指标
# precision = [report_dict[str(label)]['precision'] for label in labels]
# recall = [report_dict[str(label)]['recall'] for label in labels]
# f1_score = [report_dict[str(label)]['f1-score'] for label in labels]
#
# # 绘制精确度、召回率和 F1 分数的直方图
# fig, axs = plt.subplots(3, 1, figsize=(10, 15))
#
# # 精确度
# axs[0].bar(labels, precision, color=['blue', 'orange'])
# axs[0].set_title('Precision')
# axs[0].set_ylabel('Precision')
#
# # 召回率
# axs[1].bar(labels, recall, color=['blue', 'orange'])
# axs[1].set_title('Recall')
# axs[1].set_ylabel('Recall')
#
# # F1 分数
# axs[2].bar(labels, f1_score, color=['blue', 'orange'])
# axs[2].set_title('F1 Score')
# axs[2].set_ylabel('F1 Score')
#
# # 自动调整布局
# plt.tight_layout()
#
# # 显示图形
# plt.show()

